#include <vcl.h>
#pragma hdrstop

#include "OpenDirectory.h"
#include "EIC.h"
#include <FileCtrl.hpp>
#include <WindowsX.h>
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé est utilisé pour être sûr que les composants créés n'ont
// aucune fonction virtuelle pure.
//
#define HANDLE_EDIT  14148

static inline void ValidCtrCheck(COpenDirectory *)
{
  new COpenDirectory(NULL);
}



typedef struct
  {
    const char *pcszInitialPath;
  } SELECTPATH_PARAM;

static int CALLBACK SelectPathCallback(HWND hdlgBrowser,UINT uMsg,LPARAM lParam,LPARAM lpData)
{
 ASSERT( lpData);

 switch( uMsg)
 { // L'utilisateur vient de sélectionner un nouveau dossier shell
   // => Activation/Désactivation de la commande de sélection s'il s'agit ou non d'un répertoire de type fichier
   case BFFM_SELCHANGED :
     { bool       bIsFilePath;
       SHFILEINFO fi;
       TCHAR szDir[MAX_PATH];
       HWND Handle;
       for(;;)
       {
         if( ::SHGetFileInfo( (LPCTSTR)lParam, 0, &fi, sizeof( fi), SHGFI_ATTRIBUTES | SHGFI_PIDL))
           if( ( fi.dwAttributes & ( SFGAO_FILESYSTEM | SFGAO_FOLDER)) == ( SFGAO_FILESYSTEM | SFGAO_FOLDER))
           { bIsFilePath = true; break;}
         bIsFilePath = false; break;
       }
       SendMessage( hdlgBrowser, BFFM_ENABLEOK, 0, bIsFilePath);


       if (SHGetPathFromIDList((LPITEMIDLIST) lParam ,szDir)) {
          Handle = GetDlgItem(hdlgBrowser, HANDLE_EDIT);
          SendMessage(Handle,WM_SETTEXT,0,(long)szDir);
       }

     }
     break;

   case BFFM_VALIDATEFAILED:
       TCHAR szDir[MAX_PATH];
       TCHAR szMessage[MAX_PATH];
       HWND Handle;
       Handle = GetDlgItem(hdlgBrowser, HANDLE_EDIT);
       SendMessage(Handle,WM_GETTEXT,MAX_PATH,(long)szDir);

       if ((szDir[0] == '\\' && szDir[1] == '\\') || (szDir[1] == ':' && szDir[2] == '\\'))
          {
          if (::MessageBox (hdlgBrowser, "Ce répertoire n'existe pas, voulez-vous le créer ?", "question", MB_YESNO) == IDYES)
              {
              if (!CreateDirectory(szDir, NULL))
                  {
                  strcpy(szMessage, "Le dossier spécifié :\n\n");
                  strncat(szMessage, szDir, MAX_PATH);
                  strncat(szMessage, "\n\nn'est pas accessible en écriture.", MAX_PATH);
                  ::MessageBox (hdlgBrowser, szMessage, "Attention", MB_OK);
                  }
              }
          }
       else
          {
          strcpy(szMessage, "Le dossier spécifié :\n\n");
          strncat(szMessage, szDir, MAX_PATH);
          strncat(szMessage, "\n\nn'est pas valide ou incomplet. Veuillez \ntaper un chemin d'accés complet avec la lettre du lecteur, par \nexemple 'C:\\APPS'", MAX_PATH);
          ::MessageBox (hdlgBrowser, szMessage, "Attention", MB_OK);
          return 1;
          }
       return 1;
       break;

   // Initialisation du dialogue de parcours d'un répertoire
   // => Sélection du répertoire par défaut et positionnement du dialogue dans son possesseur
   case BFFM_INITIALIZED :
     { HWND            hwndOwner;
       RECT            rOwner;
       WINDOWPLACEMENT wndpl;
       int             nLenInitialPath;
       char*           pszInitialPath;

       ASSERT( ((SELECTPATH_PARAM*)lpData)->pcszInitialPath);
       if( ( nLenInitialPath = strlen( pszInitialPath = (char*)((SELECTPATH_PARAM*)lpData)->pcszInitialPath)) > 0)
       try { // Un chemin initial existe
         // => On ôte son éventuel '\\' terminal (si ce n'est pas le répertoire racine d'une unité)
         if( pszInitialPath[ nLenInitialPath - 1] != '\\')
           nLenInitialPath = 0;
         else if( ( nLenInitialPath == 3) && ( pszInitialPath[ 1] == ':'))
           nLenInitialPath = 0;
         else
           strncpy( pszInitialPath = new char[ nLenInitialPath], pszInitialPath, nLenInitialPath)[ nLenInitialPath - 1] = '\0';
         SendMessage( hdlgBrowser, BFFM_SETSELECTION, true, (LPARAM)pszInitialPath);
       } catch(...) {
         // Erreur (très certainement) d'allocation => Pas de message
       }
       if( nLenInitialPath)
         delete[] pszInitialPath;

       wndpl.length  = sizeof( wndpl);
       wndpl.showCmd = SW_SHOW;
       if( ( hwndOwner = ::GetWindow( hdlgBrowser, GW_OWNER)) != NULL)
       if( ::GetWindowRect( hwndOwner, &rOwner))
       if( ::GetWindowPlacement( hdlgBrowser, &wndpl))
       if( ::OffsetRect( &wndpl.rcNormalPosition,
                         ( rOwner.left + rOwner.right - wndpl.rcNormalPosition.left - wndpl.rcNormalPosition.right) / 2,
                         ( 2 * ( rOwner.top - wndpl.rcNormalPosition.top) + rOwner.bottom - wndpl.rcNormalPosition.bottom) / 3))
         ::SetWindowPlacement( hdlgBrowser, &wndpl);
     }
     break;

   default : ASSERT( false);
 }
 return 0;
}



__fastcall COpenDirectory::COpenDirectory(TComponent* Owner) : TComponent(Owner)
{
  m_Texte = "Sélectionnez un répertoire";
  m_Options = Option() << RepertoiresSeulement;
  m_AntiSlashFinal = false;
}



bool __fastcall COpenDirectory::Execute()
{
  bool Resultat = false;
  int lnResult = SetErrorMode(SEM_FAILCRITICALERRORS);      //Pour éviter d'avoir la fenêtre comme quoi le lecteur n'est pas prêt sous W2K
  LPMALLOC pMalloc = NULL;
  SELECTPATH_PARAM spp;
  char szFolderName[MAX_PATH + 1];
  BROWSEINFO bi;
  LPITEMIDLIST pidl;
  AnsiString Chemin;
  memset(&bi,0,sizeof(bi));
  bi.hwndOwner = Screen->ActiveCustomForm ? Screen->ActiveCustomForm->Handle : (Application->MainForm)?Application->MainForm->Handle:GetActiveWindow();
  bi.pszDisplayName = szFolderName;
  bi.lpszTitle = m_Texte.c_str();
  bi.ulFlags = 0;
  if (m_Options.Contains(OrdinateursSeulement))
    bi.ulFlags |= BIF_RETURNONLYFSDIRS;
  if (m_Options.Contains(ImprimantesSeulement))
    bi.ulFlags |= BIF_BROWSEFORPRINTER;
  if (m_Options.Contains(NePasSelectionnerlesRepertoiresReseau))
    bi.ulFlags |= BIF_DONTGOBELOWDOMAIN;
  if (m_Options.Contains(VoirCorbeilleIE))
    bi.ulFlags |= BIF_RETURNFSANCESTORS;
  if (m_Options.Contains(RepertoiresSeulement))
    bi.ulFlags |= BIF_RETURNONLYFSDIRS;
  if (m_Options.Contains(EditControl))
    bi.ulFlags |= BIF_EDITBOX | BIF_VALIDATE;
/*  if (m_Options.Contains(InclureTexteStatus))
    bi.ulFlags |= BIF_STATUSTEXT;*/
  bi.lpfn = SelectPathCallback;
  bi.lParam = (long)&spp;
  bi.pidlRoot = 0;
  if (m_RepertoireInitial.IsEmpty() || !DirectoryExists(m_RepertoireInitial))
    Chemin = GetCurrentDir();
  else
    Chemin = m_RepertoireInitial;
  spp.pcszInitialPath = Chemin.c_str();
  pidl = ::SHBrowseForFolder(&bi);
  if (pidl)
    {
      Resultat = ::SHGetPathFromIDList(pidl,szFolderName);
      if (Resultat)
        {
          m_Repertoire = szFolderName;
          if (m_AntiSlashFinal)
            {
              if (!m_Repertoire.IsEmpty() && (m_Repertoire[m_Repertoire.Length()] != '\\'))
                m_Repertoire = m_Repertoire + '\\';
            }
          else
            {
              if (!m_Repertoire.IsEmpty() && (m_Repertoire[m_Repertoire.Length()] == '\\') && (m_Repertoire.Length() != 3))
                m_Repertoire.Delete(m_Repertoire.Length(),1);
            }
        }
      SHGetMalloc(&pMalloc);
      pMalloc->Free(pidl);
      pMalloc->Release();
    }
  lnResult = SetErrorMode(lnResult);
  return Resultat;
}



namespace Opendirectory
{
  void __fastcall PACKAGE Register()
  {
     TComponentClass classes[1] = {__classid(COpenDirectory)};
     RegisterComponents("Dialogues", classes, 0);
  }
}



